package de.teamgamma.cansat.groundstation.export;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Date;
import java.util.HashMap;

import javax.swing.JFileChooser;

import org.jfree.chart.ChartFactory;
import org.jfree.chart.JFreeChart;
import org.jfree.data.time.FixedMillisecond;
import org.jfree.data.time.TimeSeries;
import org.jfree.data.time.TimeSeriesCollection;

import de.szut.gui.language.Languages;
import de.szut.gui.language.TranslatableComponent;
import de.szut.gui.language.TranslatableFileChooser;
import de.szut.gui.language.TranslatableStyledButton;
import de.teamgamma.cansat.groundstation.control.Controller;
import de.teamgamma.cansat.groundstation.main.DefaultPanel;
import de.teamgamma.cansat.groundstation.main.MainMenuPanel;
import de.teamgamma.cansat.groundstation.options.OptionKeys;

/**
 * Panel for exporting
 * @author Marc Huisinga
 *
 */

public class ExportPanel extends DefaultPanel {

	private static final long serialVersionUID = 8904475010716470351L;
	
	/**
	 * Key for the show-button
	 */
	public static final String SHOWKEY = "show";
	/**
	 * Key for the picture viewer
	 */
	public static final String VIEWERKEY = "viewer";
	/**
	 * key for the .txt-button
	 */
	public static final String TXTEXPORTKEY = "txtexport";
	/**
	 * key for the .csv-button
	 */
	public static final String CSVEXPORTKEY = "csvexport";
	/**
	 * key for the .xls-button
	 */
	public static final String XLSEXPORTKEY = "xlsexport";
	/**
	 * key for the .kml-button
	 */
	public static final String KMLEXPORTKEY = "kmlexport";
	/**
	 * Button width of the export buttons on this panel
	 */
	public static final int BUTTONWIDTH = 380;
	/**
	 * Button height of the export buttons on this panel
	 */
	public static final int BUTTONHEIGHT = 25;
	/**
	 * X-Position of all export buttons
	 */
	public static final int EXPORTBUTTONSTARTPOSITIONX = Controller.getInstance().getGuiController().getMainFrame().getWidth()/2-BUTTONWIDTH/2+5;
	/**
	 * Y-Position where the generation of the export buttons will start
	 */
	public static final int EXPORTBUTTONSTARTPOSITIONY = 60;
	/**
	 * Y-Margin between the export buttons
	 */
	public static final int DISTBETWEENEXPORTBUTTONSY = 50;
	/**
	 * All export button keys
	 */
	public static final ArrayList<String> EXPORTBUTTONS = new ArrayList<String>();
	static {
		EXPORTBUTTONS.add(SHOWKEY);
		EXPORTBUTTONS.add(VIEWERKEY);
		EXPORTBUTTONS.add(TXTEXPORTKEY);
		EXPORTBUTTONS.add(CSVEXPORTKEY);
		EXPORTBUTTONS.add(XLSEXPORTKEY);
		EXPORTBUTTONS.add(KMLEXPORTKEY);
	}
	
	private ArrayList<TranslatableComponent> translatableComponents;
	
	private HashMap<String,TranslatableStyledButton> exportButtons;
	
	public ExportPanel() {
		
		translatableComponents = new ArrayList<TranslatableComponent>();
		exportButtons = new HashMap<String,TranslatableStyledButton>();
		
		Languages.prepareComponent("export.ExportPanel.header", getHeader(), translatableComponents);
		Languages.prepareComponent("export.ExportPanel.return", getReturnButton(), translatableComponents);
		getReturnButton().addActionListener(new ActionListener() {
			@Override
			public void actionPerformed(ActionEvent arg0) {
				Controller.getInstance().getGuiController().toggleCurrentPanel(new MainMenuPanel());
			}
		});
		
		
		int currentYPos = EXPORTBUTTONSTARTPOSITIONY;
		for (String currentKey : EXPORTBUTTONS) {
			TranslatableStyledButton currentButton = new TranslatableStyledButton();
			Languages.prepareComponent("export.ExportPanel." + currentKey.toLowerCase(), currentButton, translatableComponents);
			currentButton.setBounds(EXPORTBUTTONSTARTPOSITIONX, currentYPos, BUTTONWIDTH, BUTTONHEIGHT);
			exportButtons.put(currentKey, currentButton);
			add(currentButton);
			currentYPos += DISTBETWEENEXPORTBUTTONSY;
		}
		
		exportButtons.get(SHOWKEY).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				ExportableData data = selectInput();
				if (data != null) {
					Controller.getInstance().getGuiController().toggleCurrentPanel(new ShowPanel(generateChart(data)));
				}
			}
		});
		
		exportButtons.get(VIEWERKEY).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				String[] pics = selectPicDirectory();
				if (pics != null) {
					Controller.getInstance().getGuiController().toggleCurrentPanel(new PicViewerPanel(pics));
				}
			}
		});
		
		exportButtons.get(TXTEXPORTKEY).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				ExportableData data = selectInput();
				if (data != null) {
					File output = selectOutput();
					if (output != null) {
						TxtExporter exporter = new TxtExporter();
						exporter.export(data, output);
					}
				}
			}
		});
		
		exportButtons.get(CSVEXPORTKEY).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				ExportableData data = selectInput();
				if (data != null) {
					File output = selectOutput();
					if (output != null) {
						CsvExporter exporter = new CsvExporter();
						exporter.export(data, output);
					}
				}
			}
		});
		
		exportButtons.get(XLSEXPORTKEY).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				ExportableData data = selectInput();
				if (data != null) {
					File output = selectOutput();
					if (output != null) {
						XlsExporter exporter = new XlsExporter();
						exporter.export(data, output);
					}
				}
			}
		});
		
		exportButtons.get(KMLEXPORTKEY).addMouseListener(new MouseAdapter() {
			@Override
			public void mouseClicked(MouseEvent e) {
				ExportableData data = selectInput();
				if (data != null) {
					File output = selectOutput();
					if (output != null) {
						KmlExporter exporter = new KmlExporter();
						exporter.export(data, output);
					}
				}
			}
		});
		
		Controller.getInstance().getGuiController().getLanguages().translateListOfComponents(translatableComponents);
	}
	
	private ExportableData selectInput() {
		TranslatableFileChooser chooser = new TranslatableFileChooser();
		chooser.setTranslationKey("export.ExportPanel.inputchooser");
		Controller.getInstance().getGuiController().getLanguages().translateSpecificComponent(chooser);
		chooser.setCurrentDirectory(new File(Controller.getInstance().getOptions().getOptionValue(OptionKeys.EXPINLOCKEY)));
		int choice = chooser.showOpenDialog(null);
		if (choice == JFileChooser.APPROVE_OPTION) {
			File inputFile = chooser.getSelectedFile();
			if (inputFile.exists()) {
				ExportableData data = new ExportableData();
				data.importData(inputFile);
				return data;
			} else {
				System.err.println("File doesn't exist!");
			}
		}
		return null;
	}
	
	private String[] selectPicDirectory() {
		TranslatableFileChooser chooser = new TranslatableFileChooser();
		chooser.setTranslationKey("export.ExportPanel.dirchooser");
		Controller.getInstance().getGuiController().getLanguages().translateSpecificComponent(chooser);
		chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
		int choice = chooser.showOpenDialog(null);
		if (choice == JFileChooser.APPROVE_OPTION) {
			File inputFile = chooser.getSelectedFile();
			if (inputFile.exists()) {
				String[] picNames = inputFile.list();
				String[] picLocs = new String[picNames.length];
				String dirLoc = inputFile.getPath();
				for (int i = 0; i != picNames.length; i++) {
					picLocs[i] = new File(dirLoc,picNames[i]).getPath();
				}
				// Sort pics
				Arrays.sort(picLocs, new Comparator<String>(){
				    public int compare(String f1, String f2) {
				        return Long.valueOf(new File(f1).lastModified()).compareTo(new File(f2).lastModified());
				    }
				    });
				return picLocs;
			} else {
				System.err.println("File doesn't exist!");
			}
		}
		return null;
	}
	
	private File selectOutput() {
		TranslatableFileChooser chooser = new TranslatableFileChooser();
		chooser.setTranslationKey("export.ExportPanel.outputchooser");
		Controller.getInstance().getGuiController().getLanguages().translateSpecificComponent(chooser);
		int choice = chooser.showSaveDialog(null);
		if (choice == JFileChooser.APPROVE_OPTION) {
			File outputFile = chooser.getSelectedFile();
			if (outputFile.getAbsolutePath().indexOf(".") == -1) {
				return outputFile;
			}
		}
		return null;
	}
	
	private JFreeChart generateChart(ExportableData data) {
		String[] keys = data.getKeys();
		String[] valueKeys = new String[keys.length-1];
		for (int i = 1; i != keys.length; i++) {
			valueKeys[i-1] = keys[i];
		}
		
		FixedMillisecond[] timeData;
		{
			String[] tData = data.getDataOfKey(keys[0]);
			int tDataLength = tData.length;
			timeData = new FixedMillisecond[tDataLength];
			for (int i = 0; i != tDataLength; i ++) {
				timeData[i] = new FixedMillisecond(new Date(Long.valueOf(tData[i].split("\\.")[0])));
			}
		}
		
		HashMap<String,String> units = new HashMap<String,String>();
		{
			String[] tUnits = data.getUnits();
			for (int i = 0; i != keys.length; i++) {
				units.put(keys[i], tUnits[i]);
			}
		}
		
		String[] dataOfKey;
		TimeSeriesCollection dataset = new TimeSeriesCollection();
		for (String currentDateKey : valueKeys) {
			TimeSeries timeSeries = new TimeSeries(currentDateKey + "|" + units.get(currentDateKey));
			dataOfKey = data.getDataOfKey(currentDateKey);
			for (int i = 0; i != dataOfKey.length; i++) {
				try {
					timeSeries.add(timeData[i], Double.valueOf(dataOfKey[i]));
				} catch(NumberFormatException e) {/* Value is not being added to the series since it's gps data most likely.*/}
				
			}
			dataset.addSeries(timeSeries);
		}
		
		return ChartFactory.createTimeSeriesChart(
				"",
	            "", 
	            "",
	            dataset
	    );
	}

}
